package com.jiyici.fragment;

import java.util.ArrayList;
import java.util.Calendar;
import java.util.List;

import jiyici.Constant.ItemParamType;
import android.content.Context;
import android.content.Intent;
import android.content.res.Resources;
import android.os.AsyncTask;
import android.os.Bundle;
import android.os.SystemClock;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import android.widget.TextView;

import com.inqbarna.tablefixheaders.TableFixHeaders;
import com.inqbarna.tablefixheaders.adapters.BaseTableAdapter;
import com.jiyici.ItemHolder;
import com.jiyici.R;
import com.jiyici.RecordActivity;
import com.jiyici.controller.DataManager.DataListener;
import com.jiyici.data.ClientDBHelper;
import com.jiyici.model.Item;
import com.jiyici.model.ItemParam;
import com.jiyici.model.ModelUtil;
import com.jiyici.model.Record;
import com.jiyici.utils.DateGroup;
import com.jiyici.utils.DateUtil;
import com.jiyici.utils.LogUtil;

import fr.castorflex.android.flipimageview.library.FlipImageView;

public class RecordListFragment extends BaseFragment implements DataListener {

    private static final String TAG = "record-table";

    private ArrayList<Record> mRecordList;
    
    private int[] mDateGroup;

    private TableFixHeaders mTable;
    
    private void getDateGroup() {
        int size = mRecordList.size();
        ArrayList<Calendar> dateList = new ArrayList<Calendar>(size + 1);
        for (int i = 0; i < size; i++) {
            Calendar c = Calendar.getInstance();
            c.setTimeInMillis(mRecordList.get(i).recordTime);
            dateList.add(c);
        }
        mDateGroup = DateGroup.getDateGroup(dateList);
//        size = mDateGroup.length;
//        int prevGroup = DateGroup.GROUP_INVALID;
//        for (int i = 0; i < size; i++) {
//            int group = mDateGroup[i];
//            if (group == prevGroup)
//                mDateGroup[i] = DateGroup.GROUP_INVALID;
//            prevGroup = group;
//        }
    }
    
    @Override
    public void onItemCatgoryChanged() {
        TableAdapter2 tableAdapter = (TableAdapter2)mTable.getAdapter();
        tableAdapter.setItem(getItem());
        tableAdapter.notifyDataSetChanged();
    }
    
    private Item getItem() {
        return ((ItemHolder) getActivity()).getItem();
    }

    @Override
    public void onRecordChanged() {
        new AsyncTask<Void, Void, Void>() {

            @Override
            protected Void doInBackground(Void... params) {
                Item item = getItem();
                mRecordList = ClientDBHelper.getInstance().dbQueryRecord(item.getId());
                SortStatus sortStatus = (SortStatus) mTable.getTag();
                ItemParam sortParam = sortStatus.sortColumn >= 0 ? item.params.get(sortStatus.sortColumn) : null;
                ModelUtil.sordRecord(mRecordList, sortParam, sortStatus.sort);
                if (isDateSort())
                    getDateGroup();
                return null;
            }

            @Override
            protected void onPostExecute(Void result) {
                ((TableAdapter2)mTable.getAdapter()).notifyDataSetChanged();
            }
            
        }.execute();
    }

    private static class SortStatus {
        int sortColumn;
        int sort;

        public SortStatus(int sortColumn, int sort) {
            super();
            this.sortColumn = sortColumn;
            this.sort = sort;
        }
    }

    @Override
    public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) {
        super.onCreateView(inflater, container, savedInstanceState);
        View view = inflater.inflate(R.layout.fragment_record_list, container, false);
        mTable = (TableFixHeaders) view.findViewById(R.id.table);
        mTable.setTag(new SortStatus(-1, ModelUtil.SORT_DESC)); /*
                                                                 * current sort
                                                                 * column
                                                                 */
        new AsyncTask<Void, Void, Void>() {

            @Override
            protected Void doInBackground(Void... params) {
                mRecordList = ClientDBHelper.getInstance().dbQueryRecord(getItem().getId());
                ModelUtil.sordRecord(mRecordList, null, ModelUtil.SORT_DESC);
                getDateGroup();
                return null;
            }

            @Override
            protected void onPostExecute(Void result) {
                mTable.setAdapter(new TableAdapter2(getActivity(), getItem()));
            }

            @Override
            protected void onPreExecute() {
                super.onPreExecute();
            }

        }.execute();
        return view;
    }
    
    static class Matrix {
        public int row;
        public int column;
        public Matrix(int row, int column) {
            super();
            this.row = row;
            this.column = column;
        }
    }
    
    private boolean isDateSort() {
        return ((SortStatus)mTable.getTag()).sortColumn == -1;
    }
    
    class TableAdapter2 extends BaseTableAdapter implements View.OnClickListener {
        
        private final Context context;
        private final LayoutInflater inflater;
        private int widthText;
        private int widthNumber;
        private int rowHeight;
        private int rowHeightWithGroup;
        private Item mItem;
        
        public TableAdapter2(Context context, Item item) {
            this.context = context;
            inflater = LayoutInflater.from(context);
            Resources resources = context.getResources();
            widthText = resources.getDimensionPixelSize(R.dimen.width_text);
            widthNumber = resources.getDimensionPixelSize(R.dimen.width_number);
            rowHeight = resources.getDimensionPixelSize(R.dimen.table_row_height);
            rowHeightWithGroup = resources.getDimensionPixelSize(R.dimen.table_row_height_with_group);
            mItem = item;
        }
        
        public void setItem(Item item) {
            mItem = item;
        }

        @Override
        public int getRowCount() {
            return mRecordList.size();
        }

        @Override
        public int getColumnCount() {
            return mItem.params.size();
        }

        @Override
        public View getView(int row, int column, View convertView, ViewGroup parent) {
            int viewType = getItemViewType(row, column);
            TextView groupText = null;
            if (convertView == null) {
                convertView = inflater.inflate(getLayoutResource(viewType, row, column), parent, false);
                if (viewType == 2) {
                    groupText = (TextView) convertView.findViewById(R.id.group);
                    groupText.setVisibility(View.VISIBLE);
                }
            }

            TextView contentText = ((TextView) convertView.findViewById(android.R.id.text1));
            contentText.setText(getCellString(row, column));
            if (viewType == 2) {
                if (groupText == null)
                    groupText = (TextView) convertView.findViewById(R.id.group);
                if (column == -1) {
//                    groupText.setText(DateGroup.getGroupName(mDateGroup[row]));
                    int group = mDateGroup[row];
                    if (group != DateGroup.GROUP_THIS_WEEK_AFTER_TOMORROW && group != DateGroup.GROUP_THIS_WEEK_BEFORE_YESTERDAY)
                        groupText.setText(DateUtil.getGroupName(group));
                    else
                        groupText.setText(DateUtil.getDateWeekName(mRecordList.get(row).recordTime));
                }
                else
                    groupText.setText("");
            }
            if (viewType == 0) {
                convertView.setOnClickListener(this);
                convertView.setTag(new Matrix(row, column));
            } else {
                contentText.setOnClickListener(this);
                contentText.setTag(new Matrix(row, column));
            }
            onGetView(convertView, row, column);
            return convertView;
        }
        
        private int getLayoutResource(int viewType, int row, int column) {
            final int layoutResource;
            switch (viewType) {
            case 0:
                layoutResource = R.layout.table_head;
                break;
            case 1:
                layoutResource = R.layout.table_cell;
                break;
            case 2:
                layoutResource = R.layout.table_cell;
                break;
            default:
                throw new RuntimeException("wtf?");
            }
            return layoutResource;
        }
        
        private String getCellString(int row, int column) {
            if (row == -1) {
                if (column == -1) {
                    return context.getString(R.string.date);
                }
                ItemParam itemParam = mItem.params.get(column);
                return itemParam.itemParamName;
            }
            Record record = mRecordList.get(row);
            if (column == -1) {
//                return DateUtil.data2String(record.recordTime);
                if (isDateSort())
                    return DateUtil.getDateOrTime(mDateGroup[row], record.recordTime);
                else
                    return DateUtil.getDateOrTime(record.recordTime);
            }
            ItemParam itemParam = mItem.params.get(column);
            return ModelUtil.getRecordItemValue(record, itemParam);
        }
        
        private void onGetView(View view, int row, int column) {
            if (row == -1) {
                FlipImageView fiv = (FlipImageView) view.findViewById(R.id.sort_icon);
                fiv.setTag(column);
                SortStatus sortStatus = (SortStatus) mTable.getTag();
                int currentSortColumn = sortStatus.sortColumn;
                boolean visible = column == currentSortColumn;
                fiv.setVisibility(visible ? View.VISIBLE : View.INVISIBLE);
                if (visible) {
                    fiv.setFlipped(sortStatus.sort == ModelUtil.SORT_ASC, false);
                } else {
                    fiv.setFlipped(false, false);
                }
                
                fiv.setClickable(false);
            }
        }

        @Override
        public int getWidth(int column) {
            if (column == -1)
                return widthText;
            ItemParam itemParam = mItem.params.get(column);
            if (itemParam.paramType == ItemParamType.TEXT)
                return widthText;
            else if (itemParam.paramType == ItemParamType.NUMBER)
                return widthNumber;
            return widthText;
        }

        @Override
        public int getHeight(int row) {
            if (getItemViewType(row, 0) == 2) {
                return rowHeightWithGroup;
            }
            return rowHeight;
        }

        @Override
        public int getItemViewType(int row, int column) {
            if (row < 0) {
                return 0;
            } else {
                if (isDateSort()) {
                    if (mDateGroup[row] == DateGroup.GROUP_THIS_WEEK_AFTER_TOMORROW
                            || mDateGroup[row] == DateGroup.GROUP_THIS_WEEK_BEFORE_YESTERDAY) {
                        if (row > 0) {
                            Calendar currentday = Calendar.getInstance();
                            currentday.setTimeInMillis(mRecordList.get(row).recordTime);
                            Calendar prevday = Calendar.getInstance();
                            prevday.setTimeInMillis(mRecordList.get(row - 1).recordTime);
                            if (DateGroup.isSameDay(currentday, prevday))
                                return 1;
                        }
                        return 2;
                    }
                    if (row > 0 && mDateGroup[row] == mDateGroup[row - 1])
                        return 1;
                    return 2;
                } else {
                    return 1;
                }
            }
        }

        @Override
        public int getViewTypeCount() {
            if (isDateSort()) {
                return 3;
            }
            return 2;
        }

        @Override
        public void onClick(View v) {
            Matrix matrix = (Matrix) v.getTag();
            if (matrix == null)
                return;
            if (matrix.row == -1) {
                final FlipImageView fiv = (FlipImageView) v.findViewById(R.id.sort_icon);
                final ItemParam sortParam;
                if (matrix.column >= 0) {
                    sortParam = mItem.params.get(matrix.column);
                } else {
                    sortParam = null;
                }
                final int sort;
                if (fiv.getVisibility() == View.VISIBLE) {
                    fiv.toggleFlip();
                    sort = fiv.isFlipped() ? ModelUtil.SORT_ASC : ModelUtil.SORT_DESC;
                } else {
                    _showSortIcon(matrix.column);
                    sort = ModelUtil.SORT_DESC;
                }
                mTable.setTag(new SortStatus(matrix.column, sort));
                new AsyncTask<Void, Void, Void>() {

                    @Override
                    protected Void doInBackground(Void... params) {
                        long time = SystemClock.uptimeMillis();
                        ModelUtil.sordRecord(mRecordList, sortParam, sort);
                        if (sortParam == null)
                            getDateGroup();
                        try {
                            time = SystemClock.uptimeMillis() - time;
                            long sleep = 200 - time;
                            if (sleep > 0)
                                Thread.sleep(sleep);
                        } catch (InterruptedException e) {
                            e.printStackTrace();
                        }
                        return null;
                    }

                    @Override
                    protected void onPostExecute(Void result) {
                        ((TableAdapter2) mTable.getAdapter()).notifyDataSetChanged();
                    }

                }.execute();
            } else {
                Intent intent = new Intent(getActivity(), RecordActivity.class);
                intent.putExtra("item", mItem);
                intent.putExtra("record", mRecordList.get(matrix.row));
                getActivity().startActivity(intent);
            }
        }
        
        private void _showSortIcon(int column) {
            FlipImageView head = (FlipImageView) mTable.getHeadView().findViewById(R.id.sort_icon);
            List<View> rowList = mTable.getRowViewList();
            if (column == -1) {
                head.setVisibility(View.VISIBLE);
                if (rowList != null) {
                    int size = rowList.size();
                    for (int i = 0; i < size; i++) {
                        FlipImageView fiv = (FlipImageView) rowList.get(i).findViewById(R.id.sort_icon);
                        fiv.setVisibility(View.INVISIBLE);
                        fiv.setFlipped(false, false);
                    }
                }
            } else {
                head.setVisibility(View.INVISIBLE);
                head.setFlipped(false, false);
                if (rowList != null) {
                    int size = rowList.size();
                    for (int i = 0; i < size; i++) {
                        FlipImageView fiv = (FlipImageView) rowList.get(i).findViewById(R.id.sort_icon);
                        try {
                            int fivColumn = ((Integer) fiv.getTag()).intValue();
                            if (column == fivColumn) {
                                fiv.setVisibility(View.VISIBLE);
                            } else {
                                fiv.setVisibility(View.INVISIBLE);
                                fiv.setFlipped(false, false);
                            }
                        } catch (Exception e) {
                            LogUtil.error(TAG, "", e);
                        }
                    }
                }
            }
        }
        
    }

}


